﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Bohdan.Arch.Messaging.Special
{
    public class CancellableWaitMessage : GeneralMessage
    {
        public override Guid TargetSubscriberId
        {
            get { return TimeMeasurerSubscriber._Id; }
        }

        protected void InitSetWaiting()
        {
            WaitForDirectMessage = true;
            WaitForCancelMessage = false;
        }

        public CancellableWaitMessage()
        {
            InitSetWaiting();
        }

        public CancellableWaitMessage(TimeSpan duration)
        {
            this.Duration = duration;
            InitSetWaiting();
        }

        EventWaitHandle ewhCancel = new EventWaitHandle(false, EventResetMode.ManualReset);
        EventWaitHandle ewhDecisionMade = new EventWaitHandle(false, EventResetMode.ManualReset);
        volatile bool _tryCancelResult = false;

        public bool WaitForDirectMessage { get; set; }
        public bool WaitForCancelMessage { get; set; }

        internal void DoWaitAndAction()
        {
            if (!ewhCancel.WaitOne(Duration))
            {
                ewhDecisionMade.Set();
                Bus.PostMessageAsync(DirectMessage);
                if (DirectMessage != null && WaitForDirectMessage)
                    DirectMessage.WaitCompleted();
            }
            else
            {
                _tryCancelResult = true;
                ewhDecisionMade.Set();
                Bus.PostMessageAsync(OnCancelMessage);
                if (OnCancelMessage != null && WaitForCancelMessage)
                    OnCancelMessage.WaitCompleted();
            }
        }

        public bool TryCancel()
        {
            ewhCancel.Set();
            ewhDecisionMade.WaitOne();
            return _tryCancelResult;
        }

        public TimeSpan Duration { get; set; }
        public GeneralMessage OnCancelMessage { get; set; }
        public GeneralMessage DirectMessage { get; set; }
    }
}
